<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Documentation SimpleTest : tester des scripts web</title>
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
</head>
<body>
<div class="menu_back">
<div class="menu">
<a href="index.html">SimpleTest</a>
                |
                <a href="overview.html">Overview</a>
                |
                <a href="unit_test_documentation.html">Unit tester</a>
                |
                <a href="group_test_documentation.html">Group tests</a>
                |
                <a href="mock_objects_documentation.html">Mock objects</a>
                |
                <a href="partial_mocks_documentation.html">Partial mocks</a>
                |
                <a href="reporter_documentation.html">Reporting</a>
                |
                <a href="expectation_documentation.html">Expectations</a>
                |
                <a href="web_tester_documentation.html">Web tester</a>
                |
                <a href="form_testing_documentation.html">Testing forms</a>
                |
                <a href="authentication_documentation.html">Authentication</a>
                |
                <a href="browser_documentation.html">Scriptable browser</a>
</div>
</div>
<h1>Documentation sur le testeur web</h1>
        This page...
        <ul>
<li>
            R&eacute;ussir &agrave; <a href="#telecharger">t&eacute;l&eacute;charger une page web</a>
        </li>
<li>
            Tester le <a href="#contenu">contenu de la page</a>
        </li>
<li>
            <a href="#navigation">Naviguer sur un site web</a> pendant le test
        </li>
<li>
            M&eacute;thodes pour <a href="#requete">modifier une requ&ecirc;te</a> et pour d&eacute;boguer
        </li>
</ul>
<div class="content">
        <p>
<a class="target" name="telecharger">
<h2>T&eacute;l&eacute;charger une page</h2>
</a>
</p>
            <p>
                Tester des classes c'est tr&egrave;s bien. Reste que PHP est avant tout un langage pour cr&eacute;er des fonctionnalit&eacute;s &agrave; l'int&eacute;rieur de pages web. Comment pouvons tester la partie de devant -- celle de l'interface -- dans nos applications en PHP ? Etant donn&eacute; qu'une page web n'est constitu&eacute;e que de texte, nous devrions pouvoir les examiner exactement comme n'importe quelle autre donn&eacute;e de test.
            </p>
            <p>
                Cela nous am&egrave;ne &agrave; une situation d&eacute;licate. Si nous testons dans un niveau trop bas, v&eacute;rifier des balises avec un motif ad hoc par exemple, nos tests seront trop fragiles. Le moindre changement dans la pr&eacute;sentation pourrait casser un grand nombre de test. Si nos tests sont situ&eacute;s trop haut, en utilisant une version fantaisie du moteur de template pour donner un cas pr&eacute;cis, alors nous perdons compl&egrave;tement la capacit&eacute; &agrave; automatiser certaines classes de test. Par exemple, l'interaction entre des formulaires et la navigation devra &ecirc;tre test&eacute; manuellement. Ces types de test sont extr&ecirc;mement fastidieux et plut&ocirc;t sensibles aux erreurs.
            </p>
            <p>
                SimpleTest comprend une forme sp&eacute;ciale de sc&eacute;nario de test pour tester les actions d'une page web. <span class="new_code">WebTestCase</span> inclut des facilit&eacute;s pour la navigation, des v&eacute;rifications sur le contenu et les cookies ainsi que la gestion des formulaires. Utiliser ces sc&eacute;narios de test ressemble fortement &agrave; <span class="new_code">UnitTestCase</span>...
<pre>
<strong>class TestOfLastcraft extends WebTestCase {
}</strong>
</pre>
                Ici nous sommes sur le point de tester le site de <a href="http://www/lastcraft.com/">Last Craft</a>. Si ce sc&eacute;nario de test est situ&eacute; dans un fichier appel&eacute; <em>lastcraft_test.php</em> alors il peut &ecirc;tre charg&eacute; dans un script de lancement tout comme des tests unitaires...
<pre>
&lt;?php<strong>
    require_once('simpletest/web_tester.php');</strong>
    require_once('simpletest/reporter.php');
    
    $test = &amp;new GroupTest('Web site tests');<strong>
    $test-&gt;addTestFile('lastcraft_test.php');</strong>
    exit ($test-&gt;run(new TextReporter()) ? 0 : 1);
?&gt;
</pre>
                J'utilise ici le rapporteur en mode texte pour mieux distinguer le contenu au format HTML du r&eacute;sultat du test proprement dit.
            </p>
            <p>
                Rien n'est encore test&eacute;. Nous pouvons t&eacute;l&eacute;charger la page d'accueil en utilisant la m&eacute;thode <span class="new_code">get()</span>...
<pre>
class TestOfLastcraft extends WebTestCase {
    <strong>
    function testHomepage() {
        $this-&gt;assertTrue($this-&gt;get('http://www.lastcraft.com/'));
    }</strong>
}
</pre>
                La m&eacute;thode <span class="new_code">get()</span> renverra "true" uniquement si le contenu de la page a bien &eacute;t&eacute; t&eacute;l&eacute;charg&eacute;. C'est un moyen simple, mais efficace pour v&eacute;rifier qu'une page web a bien &eacute;t&eacute; d&eacute;livr&eacute; par le serveur web. Cependant le contenu peut r&eacute;v&eacute;ler &ecirc;tre une erreur 404 et dans ce cas notre m&eacute;thode <span class="new_code">get()</span> renverrait encore un succ&egrave;s.
            </p>
            <p>
                En supposant que le serveur web pour le site Last Craft soit op&eacute;rationnel (malheureusement ce n'est pas toujours le cas), nous devrions voir...
<pre class="shell">
Web site tests
OK
Test cases run: 1/1, Failures: 0, Exceptions: 0
</pre>
                Nous avons v&eacute;rifi&eacute; qu'une page, de n'importe quel type, a bien &eacute;t&eacute; renvoy&eacute;e. Nous ne savons pas encore s'il s'agit de celle que nous souhaitions.
            </p>
        
        <p>
<a class="target" name="contenu">
<h2>Tester le contenu d'une page</h2>
</a>
</p>
            <p>
                Pour obtenir la confirmation que la page t&eacute;l&eacute;charg&eacute;e est bien celle que nous attendions, nous devons v&eacute;rifier son contenu.
<pre>
class TestOfLastcraft extends WebTestCase {
    
    function testHomepage() {<strong>
        $this-&gt;get('http://www.lastcraft.com/');
        $this-&gt;assertWantedPattern('/why the last craft/i');</strong>
    }
}
</pre>
                La page obtenue par le dernier t&eacute;l&eacute;chargement est plac&eacute;e dans un buffer au sein m&ecirc;me du sc&eacute;nario de test. Il n'est donc pas n&eacute;cessaire de s'y r&eacute;f&eacute;rer directement. La correspondance du motif est toujours effectu&eacute;e par rapport &agrave; ce buffer.
            </p>
            <p>
                Voici une liste possible d'assertions sur le contenu...
                <table>
<tbody>
                    <tr>
<td><span class="new_code">assertWantedPattern($pattern)</span></td><td>V&eacute;rifier une correspondance sur le contenu via une expression rationnelle Perl</td>
</tr>
                    <tr>
<td><span class="new_code">assertNoUnwantedPattern($pattern)</span></td><td>Une expression rationnelle Perl pour v&eacute;rifier une absence</td>
</tr>
                    <tr>
<td><span class="new_code">assertTitle($title)</span></td><td>Passe si le titre de la page correspond exactement</td>
</tr>
                    <tr>
<td><span class="new_code">assertLink($label)</span></td><td>Passe si un lien avec ce texte est pr&eacute;sent</td>
</tr>
                    <tr>
<td><span class="new_code">assertNoLink($label)</span></td><td>Passe si aucun lien avec ce texte est pr&eacute;sent</td>
</tr>
                    <tr>
<td><span class="new_code">assertLinkById($id)</span></td><td>Passe si un lien avec cet attribut d'identification est pr&eacute;sent</td>
</tr>
                    <tr>
<td><span class="new_code">assertField($name, $value)</span></td><td>Passe si une balise input avec ce nom contient cette valeur</td>
</tr>
                    <tr>
<td><span class="new_code">assertFieldById($id, $value)</span></td><td>Passe si une balise input avec cet identifiant contient cette valeur</td>
</tr>
                    <tr>
<td><span class="new_code">assertResponse($codes)</span></td><td>Passe si la r&eacute;ponse HTTP trouve une correspondance dans la liste</td>
</tr>
                    <tr>
<td><span class="new_code">assertMime($types)</span></td><td>Passe si le type MIME se retrouve dans cette liste</td>
</tr>
                    <tr>
<td><span class="new_code">assertAuthentication($protocol)</span></td><td>Passe si l'authentification provoqu&eacute;e est de ce type de protocole</td>
</tr>
                    <tr>
<td><span class="new_code">assertNoAuthentication()</span></td><td>Passe s'il n'y pas d'authentification provoqu&eacute;e en cours</td>
</tr>
                    <tr>
<td><span class="new_code">assertRealm($name)</span></td><td>Passe si le domaine provoqu&eacute; correspond</td>
</tr>
                    <tr>
<td><span class="new_code">assertHeader($header, $content)</span></td><td>Passe si une ent&ecirc;te t&eacute;l&eacute;charg&eacute;e correspond &agrave; cette valeur</td>
</tr>
                    <tr>
<td><span class="new_code">assertNoUnwantedHeader($header)</span></td><td>Passe si une ent&ecirc;te n'a pas &eacute;t&eacute; t&eacute;l&eacute;charg&eacute;</td>
</tr>
                    <tr>
<td><span class="new_code">assertHeaderPattern($header, $pattern)</span></td><td>Passe si une ent&ecirc;te t&eacute;l&eacute;charg&eacute;e correspond &agrave; cette expression rationnelle Perl</td>
</tr>
                    <tr>
<td><span class="new_code">assertCookie($name, $value)</span></td><td>Passe s'il existe un cookie correspondant</td>
</tr>
                    <tr>
<td><span class="new_code">assertNoCookie($name)</span></td><td>Passe s'il n'y a pas de cookie avec un tel nom</td>
</tr>
                </tbody>
</table>
                Comme d'habitude avec les assertions de SimpleTest, elles renvoient toutes "false" en cas d'&eacute;chec et "true" si c'est un succ&egrave;s. Elles renvoient aussi un message de test optionnel : vous pouvez l'ajouter dans votre propre message en utilisant "%s".
            </p>
            <p>
                A pr&eacute;sent nous pourrions effectu&eacute; le test sur le titre uniquement...
<pre>
<strong>$this-&gt;assertTitle('The Last Craft?');</strong>
</pre>
                En plus d'une simple v&eacute;rification sur le contenu HTML, nous pouvons aussi v&eacute;rifier que le type MIME est bien d'un type acceptable...
<pre>
<strong>$this-&gt;assertMime(array('text/plain', 'text/html'));</strong>
</pre>
                Plus int&eacute;ressant encore est la v&eacute;rification sur le code de la r&eacute;ponse HTTP. Pareillement au type MIME, nous pouvons nous assurer que le code renvoy&eacute; se trouve bien dans un liste de valeurs possibles...
<pre>
class TestOfLastcraft extends WebTestCase {
    
    function testHomepage() {
        $this-&gt;get('http://simpletest.sourceforge.net/');<strong>
        $this-&gt;assertResponse(200);</strong>
    }
}
</pre>
                Ici nous v&eacute;rifions que le t&eacute;l&eacute;chargement s'est bien termin&eacute; en ne permettant qu'une r&eacute;ponse HTTP 200.  Ce test passera, mais ce n'est pas la meilleure fa&ccedil;on de proc&eacute;der. Il n'existe aucune page sur <em>http://simpletest.sourceforge.net/</em>, &agrave; la place le serveur renverra une redirection vers <em>http://www.lastcraft.com/simple_test.php</em>. <span class="new_code">WebTestCase</span> suit automatiquement trois de ces redirections. Les tests sont quelque peu plus robustes de la sorte. Surtout qu'on est souvent plus int&eacute;ress&eacute; par l'interaction entre les pages que de leur simple livraison. Si les redirections se r&eacute;v&egrave;lent &ecirc;tre digne d'int&eacute;r&ecirc;t, il reste possible de les supprimer...
<pre>
class TestOfLastcraft extends WebTestCase {
    
    function testHomepage() {<strong>
        $this-&gt;setMaximumRedirects(0);</strong>
        $this-&gt;get('http://simpletest.sourceforge.net/');
        $this-&gt;assertResponse(200);
    }
}
</pre>
                Alors l'assertion &eacute;choue comme pr&eacute;vue...
<pre class="shell">
Web site tests
1) Expecting response in [200] got [302]
	in testhomepage
	in testoflastcraft
	in lastcraft_test.php
FAILURES!!!
Test cases run: 1/1, Failures: 1, Exceptions: 0
</pre>
                Nous pouvons modifier le test pour accepter les redirections...
<pre>
class TestOfLastcraft extends WebTestCase {
    
    function testHomepage() {
        $this-&gt;setMaximumRedirects(0);
        $this-&gt;get('http://simpletest.sourceforge.net/');
        $this-&gt;assertResponse(<strong>array(301, 302, 303, 307)</strong>);
    }
}
</pre>
                Maitenant &ccedil;a passe.
            </p>
        
        <p>
<a class="target" name="navigation">
<h2>Navigeur dans un site web</h2>
</a>
</p>
            <p>
                Les utilisateurs ne naviguent pas souvent en tapant les URLs, mais surtout en cliquant sur des liens et des boutons. Ici nous confirmons que les informations sur le contact peuvent &ecirc;tre atteintes depuis la page d'accueil...
<pre>
class TestOfLastcraft extends WebTestCase {
    ...
    function testContact() {
        $this-&gt;get('http://www.lastcraft.com/');<strong>
        $this-&gt;clickLink('About');
        $this-&gt;assertTitle('About Last Craft');</strong>
    }
}
</pre>
                Le param&egrave;tre est le texte du lien.
            </p>
            <p>
                Il l'objectif est un bouton plut&ocirc;t qu'une balise ancre, alors <span class="new_code">clickSubmit()</span> doit &ecirc;tre utilis&eacute; avec le titre du bouton...
<pre>
<strong>$this-&gt;clickSubmit('Go!');</strong>
</pre>
            </p>
            <p>
                La liste des m&eacute;thodes de navigation est...
                <table>
<tbody>
                    <tr>
<td><span class="new_code">get($url, $parameters)</span></td><td>Envoie une requ&ecirc;te GET avec ces param&egrave;tres</td>
</tr>
                    <tr>
<td><span class="new_code">post($url, $parameters)</span></td><td>Envoie une requ&ecirc;te POST avec ces param&egrave;tres</td>
</tr>
                    <tr>
<td><span class="new_code">head($url, $parameters)</span></td><td>Envoie une requ&ecirc;te HEAD sans remplacer le contenu de la page</td>
</tr>
                    <tr>
<td><span class="new_code">retry()</span></td><td>Relance la derni&egrave;re requ&ecirc;te</td>
</tr>
                    <tr>
<td><span class="new_code">back()</span></td><td>Identique au bouton "Pr&eacute;c&eacute;dent" du navigateur</td>
</tr>
                    <tr>
<td><span class="new_code">forward()</span></td><td>Identique au bouton "Suivant" du navigateur</td>
</tr>
                    <tr>
<td><span class="new_code">authenticate($name, $password)</span></td><td>Re-essaye avec une tentative d'authentification</td>
</tr>
                    <tr>
<td><span class="new_code">getFrameFocus()</span></td><td>Le nom de la fen&ecirc;tre en cours d'utilisation</td>
</tr>
                    <tr>
<td><span class="new_code">setFrameFocusByIndex($choice)</span></td><td>Change le focus d'une fen&ecirc;tre en commen&ccedil;ant par 1</td>
</tr>
                    <tr>
<td><span class="new_code">setFrameFocus($name)</span></td><td>Change le focus d'une fen&ecirc;tre en utilisant son nom</td>
</tr>
                    <tr>
<td><span class="new_code">clearFrameFocus()</span></td><td>Revient &agrave; un traitement de toutes les fen&ecirc;tres comme une seule</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmit($label)</span></td><td>Clique sur le premier bouton avec cette &eacute;tiquette</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmitByName($name)</span></td><td>Clique sur le bouton avec cet attribut de nom</td>
</tr>
                    <tr>
<td><span class="new_code">clickSubmitById($id)</span></td><td>Clique sur le bouton avec cet attribut d'identification</td>
</tr>
                    <tr>
<td><span class="new_code">clickImage($label, $x, $y)</span></td><td>Clique sur une balise input de type image avec ce titre ou ce texte dans l'attribut alt</td>
</tr>
                    <tr>
<td><span class="new_code">clickImageByName($name, $x, $y)</span></td><td>Clique sur une balise input de type image avec ce nom</td>
</tr>
                    <tr>
<td><span class="new_code">clickImageById($id, $x, $y)</span></td><td>Clique sur une balise input de type image avec cet attribut d'identification</td>
</tr>
                    <tr>
<td><span class="new_code">submitFormById($id)</span></td><td>Soumet un formulaire sans valeur de soumission</td>
</tr>
                    <tr>
<td><span class="new_code">clickLink($label, $index)</span></td><td>Clique sur une ancre avec ce texte d'&eacute;tiquette visible</td>
</tr>
                    <tr>
<td><span class="new_code">clickLinkById($id)</span></td><td>Clique sur une ancre avec cet attribut d'identification</td>
</tr>
                </tbody>
</table>
            </p>
            <p>
                Les param&egrave;tres dans les m&eacute;thodes <span class="new_code">get()</span>, <span class="new_code">post()</span> et <span class="new_code">head()</span> sont optionnels. Le t&eacute;l&eacute;chargement via  HTTP HEAD ne modifie pas le contexte du navigateur, il se limite au chargement des cookies. Cela peut &ecirc;tre utilise lorsqu'une image ou une feuille de style initie un cookie pour bloquer un robot trop entreprenant.
            </p>
            <p>
                Les commandes <span class="new_code">retry()</span>, <span class="new_code">back()</span> et <span class="new_code">forward()</span> fonctionnent exactement comme dans un navigateur. Elles utilisent l'historique pour relancer les pages. Une technique bien pratique pour v&eacute;rifier les effets d'un bouton retour sur vos formulaires.
            </p>
            <p>
                Les m&eacute;thodes sur les fen&ecirc;tres m&eacute;ritent une petite explication. Par d&eacute;faut, une page avec des fen&ecirc;tres est trait&eacute;e comme toutes les autres. Le contenu sera v&eacute;rifi&eacute; &agrave; travers l'ensemble de la "frameset", par cons&eacute;quent un lien fonctionnera, peu importe la fen&ecirc;tre qui contient la balise ancre. Vous pouvez outrepass&eacute; ce comportement en exigeant le focus sur une unique fen&ecirc;tre. Si vous r&eacute;alisez cela, toutes les recherches et toutes les actions se limiteront &agrave; cette unique fen&ecirc;tre, y compris les demandes d'authentification. Si un lien ou un bouton n'est pas dans la fen&ecirc;tre en focus alors il ne peut pas &ecirc;tre cliqu&eacute;.
            </p>
            <p>
                Tester la navigation sur des pages fixes ne vous alerte que quand vous avez cass&eacute; un script entier. Pour des pages fortement dynamiques, un forum de discussion par exemple, &ccedil;a peut &ecirc;tre crucial pour v&eacute;rifier l'&eacute;tat de l'application. Pour la plupart des applications cependant, la logique vraiment d&eacute;licate se situe dans la gestion des formulaires et des sessions. Heureusement SimpleTest aussi inclut <a href="form_testing_documentation.html">des outils pour tester des formulaires web</a>.
            </p>
        
        <p>
<a class="target" name="requete">
<h2>Modifier la requ&ecirc;te</h2>
</a>
</p>
            <p>
                Bien que SimpleTest n'ait pas comme objectif de contr&ocirc;ler des erreurs r&eacute;seau, il contient quand m&ecirc;me des m&eacute;thodes pour modifier et d&eacute;boguer les requ&ecirc;tes qu'il lance. Voici une autre liste de m&eacute;thode...
                <table>
<tbody>
                    <tr>
<td><span class="new_code">getTransportError()</span></td><td>La derni&egrave;re erreur de socket</td>
</tr>
                    <tr>
<td><span class="new_code">getUrl()</span></td><td>La localisation courante</td>
</tr>
                    <tr>
<td><span class="new_code">showRequest()</span></td><td>D&eacute;verse la requ&ecirc;te sortante</td>
</tr>
                    <tr>
<td><span class="new_code">showHeaders()</span></td><td>D&eacute;verse les ent&ecirc;tes d'entr&eacute;e</td>
</tr>
                    <tr>
<td><span class="new_code">showSource()</span></td><td>D&eacute;verse le contenu brut de la page HTML</td>
</tr>
                    <tr>
<td><span class="new_code">ignoreFrames()</span></td><td>Ne recharge pas les framesets</td>
</tr>
                    <tr>
<td><span class="new_code">setCookie($name, $value)</span></td><td>Initie un cookie &agrave; partir de maintenant</td>
</tr>
                    <tr>
<td><span class="new_code">addHeader($header)</span></td><td>Ajoute toujours cette ent&ecirc;te &agrave; la requ&ecirc;te</td>
</tr>
                    <tr>
<td><span class="new_code">setMaximumRedirects($max)</span></td><td>S'arr&ecirc;te apr&egrave;s autant de redirections</td>
</tr>
                    <tr>
<td><span class="new_code">setConnectionTimeout($timeout)</span></td><td>Termine la connexion apr&egrave;s autant de temps entre les bytes</td>
</tr>
                    <tr>
<td><span class="new_code">useProxy($proxy, $name, $password)</span></td><td>Effectue les requ&ecirc;tes &agrave; travers ce proxy d'URL</td>
</tr>
                </tbody>
</table>
            </p>
        
    </div>
        References and related information...
        <ul>
<li>
            La page du projet SimpleTest sur <a href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.
        </li>
<li>
            La page de t&eacute;l&eacute;chargement de SimpleTest sur <a href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.
        </li>
<li>
            <a href="http://simpletest.sourceforge.net/">L'API du d&eacute;veloppeur pour SimpleTest</a> donne tous les d&eacute;tails sur les classes et les assertions disponibles.
        </li>
</ul>
<div class="menu_back">
<div class="menu">
<a href="index.html">SimpleTest</a>
                |
                <a href="overview.html">Overview</a>
                |
                <a href="unit_test_documentation.html">Unit tester</a>
                |
                <a href="group_test_documentation.html">Group tests</a>
                |
                <a href="mock_objects_documentation.html">Mock objects</a>
                |
                <a href="partial_mocks_documentation.html">Partial mocks</a>
                |
                <a href="reporter_documentation.html">Reporting</a>
                |
                <a href="expectation_documentation.html">Expectations</a>
                |
                <a href="web_tester_documentation.html">Web tester</a>
                |
                <a href="form_testing_documentation.html">Testing forms</a>
                |
                <a href="authentication_documentation.html">Authentication</a>
                |
                <a href="browser_documentation.html">Scriptable browser</a>
</div>
</div>
<div class="copyright">
            Copyright<br>Marcus Baker 2006
        </div>
</body>
</html>
